import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Role } from '../database/entities/role.entity';
import { RolePermission } from '../database/entities/role-permission.entity';
import { RoleMenu } from '../database/entities/role-menu.entity';
import { Menu } from '../database/entities/menu.entity';
import { CreateRoleDto, UpdateRoleDto, QueryRolesDto } from './dto/roles.dto';
import { PaginationUtil } from '../common/utils/pagination.util';
import { PaginationResult } from '../common/dto/pagination.dto';

@Injectable()
export class RolesService {
  constructor(
    @InjectRepository(Role)
    private rolesRepository: Repository<Role>,
    @InjectRepository(RolePermission)
    private rolePermissionRepository: Repository<RolePermission>,
    @InjectRepository(RoleMenu)
    private roleMenuRepository: Repository<RoleMenu>,
    @InjectRepository(Menu)
    private menuRepository: Repository<Menu>,
  ) {}

  async create(createRoleDto: CreateRoleDto): Promise<Role> {
    const role = this.rolesRepository.create(createRoleDto);
    return this.rolesRepository.save(role);
  }

  async findAll(query: QueryRolesDto): Promise<PaginationResult<Role>> {
    const { name, code, status } = query;
    
    const queryBuilder = this.rolesRepository.createQueryBuilder('role');

    // 精确搜索条件
    if (name) {
      queryBuilder.andWhere('role.name = :name', { name });
    }

    if (code) {
      queryBuilder.andWhere('role.code = :code', { code });
    }

    if (status !== undefined) {
      queryBuilder.andWhere('role.status = :status', { status });
    }

    // 使用通用工具进行搜索和分页
    return PaginationUtil.searchAndPaginate(
      queryBuilder,
      query,
      'role',
      ['name', 'code', 'description'], // 关键词搜索字段
      ['sort', 'createTime', 'updateTime', 'name'] // 允许的排序字段
    );
  }

  async findById(id: number): Promise<Role> {
    const role = await this.rolesRepository.findOne({
      where: { id },
      relations: ['rolePermissions', 'rolePermissions.permission', 'roleMenus', 'roleMenus.menu'],
    });
    
    if (!role) {
      throw new NotFoundException('角色不存在');
    }
    
    console.log(`Found role ${id} with ${role.rolePermissions?.length || 0} permissions and ${role.roleMenus?.length || 0} menus`);
    console.log('Role menu IDs:', role.roleMenus?.map(rm => rm.menuId));
    
    return role;
  }

  async update(id: number, updateRoleDto: UpdateRoleDto): Promise<Role> {
    const role = await this.findById(id);
    Object.assign(role, updateRoleDto);
    return this.rolesRepository.save(role);
  }

  async remove(id: number): Promise<void> {
    const role = await this.findById(id);
    await this.rolesRepository.remove(role);
  }

  async assignPermissions(roleId: number, permissionIds: number[]): Promise<void> {
    console.log(`Assigning permissions to role ${roleId}:`, permissionIds);
    
    await this.rolePermissionRepository.delete({ roleId });
    
    if (permissionIds && permissionIds.length > 0) {
      const rolePermissions = permissionIds.map(permissionId => 
        this.rolePermissionRepository.create({ roleId, permissionId })
      );
      
      await this.rolePermissionRepository.save(rolePermissions);
      console.log(`Successfully assigned ${rolePermissions.length} permissions to role ${roleId}`);
    } else {
      console.log(`No permissions to assign to role ${roleId}`);
    }
  }

  async assignMenus(roleId: number, menuIds: number[]): Promise<void> {
    console.log(`Assigning menus to role ${roleId}:`, menuIds);
    console.log(`menuIds type:`, typeof menuIds, 'isArray:', Array.isArray(menuIds));
    
    try {
      // 删除现有的菜单权限
      const deleteResult = await this.roleMenuRepository.delete({ roleId });
      console.log(`Deleted ${deleteResult.affected} existing menu permissions for role ${roleId}`);
      
      if (menuIds && menuIds.length > 0) {
        // 获取所有菜单ID，包括父菜单
        const allMenuIds = await this.getAllMenuIdsWithParents(menuIds);
        console.log(`Original menu IDs:`, menuIds);
        console.log(`All menu IDs (including parents):`, allMenuIds);
        
        const roleMenus = allMenuIds.map(menuId => {
          console.log(`Creating role menu: roleId=${roleId}, menuId=${menuId} (type: ${typeof menuId})`);
          return this.roleMenuRepository.create({ roleId, menuId });
        });
        
        const savedRoleMenus = await this.roleMenuRepository.save(roleMenus);
        console.log(`Successfully saved ${savedRoleMenus.length} menu permissions:`, savedRoleMenus.map(rm => ({ id: rm.id, roleId: rm.roleId, menuId: rm.menuId })));
      } else {
        console.log(`No menus to assign to role ${roleId}`);
      }
    } catch (error) {
      console.error(`Error assigning menus to role ${roleId}:`, error);
      throw error;
    }
  }

  /**
   * 获取所有菜单ID，包括其父菜单
   */
  private async getAllMenuIdsWithParents(menuIds: number[]): Promise<number[]> {
    const allMenuIds = new Set<number>();
    
    for (const menuId of menuIds) {
      // 添加当前菜单ID
      allMenuIds.add(menuId);
      
      // 查找并添加所有父菜单ID
      await this.addParentMenuIds(menuId, allMenuIds);
    }
    
    return Array.from(allMenuIds);
  }

  /**
   * 递归添加父菜单ID
   */
  private async addParentMenuIds(menuId: number, allMenuIds: Set<number>): Promise<void> {
    const menu = await this.menuRepository.findOne({
      where: { id: menuId },
      select: ['id', 'parentId']
    });
    
    if (menu && menu.parentId) {
      allMenuIds.add(menu.parentId);
      // 递归查找父菜单的父菜单
      await this.addParentMenuIds(menu.parentId, allMenuIds);
    }
  }
}